<?php
namespace App\Libs\Sms;

use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendBatchSmsRequest;
use Darabonba\OpenApi\Models\Config;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest;
use api\modules\manage\models\NotificationTemplate;
use api\utils\LogUtil;
use yii\helpers\ArrayHelper;

class Aliyun
{
    private $appId;
    private $accessKeyId;
    private $accessKeySecret;
    private $signName;
    private $endpoint;
    private $client;

    public function getInstance($params)
    {
        $this->appId = $params['account'];
        $this->serviceProvider = 'aliyun';
        $this->accessKeyId = $params['secretId'];
        $this->accessKeySecret = $params['secretKey'];
        $this->endpoint = $params['host'];
        !empty($params['signName']) && $this->signName = $params['signName'];

        require_once(\Yii::getAlias('@extVendor') . DIRECTORY_SEPARATOR . 'autoload.php');

        $config = new Config([
            'protocol' => 'HTTP',
            'httpProxy' => ALIYUN_SMS_PROXY,
            'accessKeyId' => $this->accessKeyId,
            'accessKeySecret' => $this->accessKeySecret
        ]);
        $config->endpoint = $this->endpoint;
        $this->client = new Dysmsapi($config);
        return $this;
    }

    public function sendSms($phones, $params)
    {
        return $this->batchSend($phones, $params);
    }

    public function batchSend($phones, $params)
    {
        $template = NotificationTemplate::findOne(['id' => $params['templateId'] ?? 0]);
        if (empty($template)) {
            LogUtil::warn(['message' => 'template not found', 'params' => $params]);
            return [];
        }
        $ext = json_decode($template->outer_config, true);
        if (empty($template->outer_id)) {
            LogUtil::warn(['message' => 'templateCode empty', 'params' => $params, 'template' => $template]);
            return [];
        }
        $requestParams = json_encode($this->buildParams($ext['configs'], $params['object']));
        if (count($phones) == 1) {
            $sendSmsRequest = new SendSmsRequest([
                'signName' => $this->signName,
                'templateCode' => $template->outer_id,
                'phoneNumbers' => $phones[0],
                'templateParam' => $requestParams,
            ]);
            $method = 'sendSms';
        } else {
            $sendSmsRequest = new SendBatchSmsRequest([
                'signName' => $this->signName,
                'phoneNumberJson' => json_encode($phones),
                'signNameJson' => json_encode([$this->signName]),
                'templateCode' => $template->outer_id,
                'templateParamJson' => $requestParams,
            ]);
            $method = 'sendBatchSms';
        }
        LogUtil::warn(['message' => 'sendSMS by aliyun', 'request' => $sendSmsRequest->toMap(), 'phones' => $phones, 'params' => $params], 'Component-Sms');
        $response = $this->client->$method($sendSmsRequest);
        $body = $response->body ?? [];
        $result = $body->code == 'OK';
        $logs = [];
        foreach ($phones as $phone) {
            $logs[] = [
                'template_id' => $template->id,
                'phone' => $phone,
                'result' => intval($result),
                'request_params' => $requestParams,
                'response' => json_encode($body->toMap()),
            ];
        }
        return ['result' => $result, 'logs' => $logs];
    }

    private function buildParams($configs, $object)
    {
        $formated = [];
        foreach ($configs as $config) {
            $value = ArrayHelper::getValue($object, $config['field']) ?? '';
            if ($config['type'] == 'timestamp' && is_numeric($value) && !empty($config['format'])) {
                $value = date($config['format'], $value);
            }
            $formated[$config['requestKey']] = $value;
        }

        return $formated;
    }

    /**
     * @param string[] $args
     * @return void
     */
    public function send($phone, $templateCode, $templateParams)
    {
        $sendSmsRequest = new SendSmsRequest([
            'signName' => $this->signName,
            'templateCode' => $templateCode,
            'phoneNumbers' => $phone,
            'templateParam' => json_encode($templateParams)
        ]);
        return $this->client->sendSms($sendSmsRequest);
    }
}
